<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script>
    // 21-06-12-夜  补充
    /*   如果我不想让别人对 obj对象添加或删除元素 可以在忙做？
    * defineProperty 
    * defineProperties
    */

    // 当前当该属性的configurable 键值为true时 该属性的描述才能被修改 同时该属性也能从对应的对象上被删除 
    // 就是说如果    configurable 值为false时 属性就无法从对象上面删除 这个方法 仅能使对象内的 元素无法被删除 依旧可以在新对象中添加新的对象
    // 看代码示例 
    Object.defineProperty(obj,"prop",{
         configurable:false,  //configurable属性为true时 该属性的秒速符才能被修改 同时该属性也能从对应的对象上被删除 
         enumerable:false,    //enumerable  属性为true时 该属性才会出现在对象的枚举属性中
         writable:false,      //表示 是否可以修改属性的值 
         value:""             //该属性的值 可以是任何有效的js 值(数值，对象，函数)
     })
    //这样设置以后 prop属性就变成了不能删除 不能重新修改特性 不可枚举 不能修改的属性值的属性 

    //  示例代码 
    const obj = {name:"常东东"}
    Object.defineProperty(obj,"name",{
        writable:false,
        configurable:false
    })
    // 修改 
    obj.name = "收购腾讯";
    console.log(obj.name);      //常东东 
    // 添加新的属性  
    obj.address = "青岛"
    console.log(obj.address);   //青岛


//---------------------------------------------------------    
   
    Object.freeze(person);
    // 冻结的对象既不可扩展，又是密封的，而且对象，数据属性的[ [Writable] ]特性会被设置为false。
    // 如果定义[ [Set] ]函数，访问器属性仍然是可写的。ES5定义的Object. freeze()方法可以用来冻结对象。
    var person = {
        name: "大黄"
    };
    Object.freeze(person);     //冻结了这个对象 
    person.age = 18;           //新添加一个age属性 没有起效果
    console.log(person.age);   //undefined
    delete person.name;        //删去name属性 没有起效果
    console.log(person.name);  //"大黄"
    person.name = "咪咪";      //改变已有的属性 没起到效果 
    console.log(person.name);  //"大黄"
    // Object. isFrozen()方法用于检测冻结对象。因为冻结对象既是密封的又是不可扩展的，
    // 所以用Object.isExtensible()和Object.isSealed ()检测冻结对象将分别返回false和true。
    var person = {
        name: "老王"
    };
    alert(Object.isExtensible(person)); //true
    alert(Object.isSealed(person));     //false
    alert(Object.isFrozen(person));     //false
    Object.freeze(person);
    alert(Object.isExtensible(person)); //false
    alert(Object.isSealed(person));     //true
    alert(Object.isFrozen(person));     //true

//---------------------------------------------------------    
    Object.seal()
    /*  这个方法封闭(密封)一个对象 阻止添加新属性 并将所有的属性标记为不可配置 
        当前属性的值 只要原来的可写的 就可以改变
    */
    /*
        一个对象是可拓展的(可以添加新的属性) 
       1 密封一个对象会让这个对象变得不能添加新属性
         且所有已有的属性会变得 不可配置(属性不可配置的效果 即属性不可删除)  
       2 以及一个数据属性 不能被重新定义成为访问器属性 或者反之 
         但属性的值仍然可以修改  
       3 尝试删除一个密封对象的属性或者
         将某个密封对象的属性从数据属性 转换为访问器属性 结果会静默抛出TypeError  
    */
    //看示例代码 
    var person = {
        name: "收购百度"
    }
    Object.seal(person);     //封闭这个对象

    person.age = 19;
    console.log(person.age); //undefined
                             //无法给密封对象添加属性
    delete person.name;
    console.log(person.name);//收购百度
                             //无法修改密封对象中的属性。
    //使用Object.isSealed() 方法确定对象是否被密封 而且由于被密封的对象不可扩展，所以Object.isExtensible() 检测也会返回 false。
    var person = {
        name: "老王"
    }
    Object.seal(person);

    console.log(Object.isSealed(person)); //true
    console.log(Object.isExtensible(person)); //false




//es5的防止篡改对象 
        //但是要注意，一旦把对象定义为防篡改对象，就无法撤销了。
        //默认情况下，所有对象都是可以扩展的。也就是说，任何时候都可以向对象中添加属性和方法。比如
    //Object.preventExtensions() 方法
            //1 改变这一行为 不能再添加属性或者方法。
            //2 虽然不能扩展该对象，但是不影响原有的属性，原有的属性仍然可以进行修改或者删除。
            var person = {
                name: "收购腾讯"
            }
            Object.preventExtensions(person); //将person设置为不可扩展对象
            person.money = 14;
            console.log(person);              //{name: "收购腾讯"}
            console.log(person.money);        //undefined
            person.name = "收购阿里 ";
            console.log(person.name);         //收购阿里
    //使用 Object.isExtensible() 方法可以确定该对象是否为可扩展对象。    
        var p = {
            name: "老王"
        }
        console.log(Object.isExtensible(p)); //ture
        Object.preventExtensions(p);         //将p设置为不可扩展对象
        console.log(Object.isExtensible(p)); //false

        //注意：在对防篡改对象或者冻结对象时，在非严格模式和严格模式下，抛出的结果不一样 


//夜里 补充 
        /*  在es5中,可以用Object.defineProperty()让数组的length属性变为只读的 */
        a = [1,2,3];
        Object.defineProperty(a,"length",{
            writable:false
        })
        a.length;    //不会改变的 




</script>